import tkinter as tk
from tkinter import ttk
from typing import Iterable, Type, TypeVar
import zipfile

import threading
from docx.opc.exceptions import PackageNotFoundError

from TextSearch import *
from TextSearch.app import *

VERSION = "0.1.0"

set_data_folder(pjoin(dirname(__file__), "data"))


def text_match(para: str, words: Iterable[str]) -> bool:
    for word in words:
        if para.lower().find(word.lower()) == -1:
            return False
    return True


class DocsSearchFrame(tk.Frame):
    def __init__(self, master: tk.Tk):
        super().__init__(master=master)

        self.selector = PathsList(self)
        self.selector.pack(pady=12, padx=12, fill="x")

        # def layout(master: tk.Tk):
        self.indexer = Horizontal(self)

        self.progress_bar = ttk.Progressbar(self.indexer, maximum=100, length=200)
        self.start_button = ttk.Button(
            self.indexer, text="开始扫描", command=self.start_scan
        )
        self.indexer.add(self.progress_bar, expand=True)
        self.indexer.add(self.start_button, padx=6)
        self.indexer.pack(pady=12, padx=12, fill="x")
        self.label = ttk.Label(self, text="")
        self.label.pack(pady=5, padx=12, fill="x")

        self.search_bar = SearchBar(self, self.on_search)
        self.search_bar.pack(pady=12, padx=12, fill="x")
        self.search_bar.entry.insert(tk.LEFT, "")

        self.findings = FindingsShow(self)
        self.findings.pack(pady=12, padx=12, fill="both", expand=True)

    def on_search(self, text: str):
        if text.strip() == "":
            return
        search_words = [word.strip() for word in text.split(" ") if word.strip() != ""]
        findings = []
        for doc_info in iter_documents_info():
            paragraphs = doc_info.paragraphs.filter(
                lambda para: text_match(para, search_words)
            ).l
            table_contents = doc_info.tables.map(
                lambda table: (
                    MelodieGenerator(table.cells)
                    .filter(lambda cell: text_match(cell.text, search_words))
                    .map(lambda cell: cell.text)
                    .l
                )
            ).reduce(lambda a, b: a + b, [])

            if len(paragraphs) + len(table_contents) > 0:
                print(doc_info, paragraphs)
                findings.append(Finding(doc_info, paragraphs + table_contents))
        # self.findings.update_data(findings)
        self.findings.update_data_reversed(findings)
        self.label.config(text=f"查找关键词“{text}”完成,找到{len(findings)}个文件")

    def start_scan(self):
        self.indexing_thread = threading.Thread(target=self.update_progress_bar)
        self.indexing_thread.daemon = True
        self.indexing_thread.start()

    def update_progress_bar(self):
        documents = (
            MelodieGenerator(AppConfig().paths)
            .map(
                lambda path: (
                    iter_documents_in_folder(path)
                    .filter(
                        lambda doc: (not basename(doc).startswith("~$"))
                        and doc.endswith(SUPPORTED_EXTENSIONS)
                    )
                    .l
                )
            )
            .reduce(lambda x, y: x + y, [])
        )
        docs_num = MelodieFrozenGenerator(documents).len
        for i, doc in enumerate(documents):
            self.progress_bar["value"] = ((i + 1) / docs_num) * 100
            print(i, docs_num, doc, self.progress_bar["value"])
            self.label.config(text=f"正在分析 {i+1}/{docs_num}: {basename(doc)}")
            ext = os.path.splitext(doc)[1]
            try:
                info = TEXT_EXTRACTORS[ext](doc)
                dump_document(info)
            except KeyError:
                import traceback

                traceback.print_exc()
            except OSError:
                import traceback

                traceback.print_exc()
            except AlreadyIndexed:
                print("skipped!")
                continue
            except ValueError:
                continue
            except (PackageNotFoundError, zipfile.BadZipFile):
                import traceback

                traceback.print_exc()
        self.label.config(text="扫描完成")


TabType = TypeVar("TabType")


class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        high_dpi_adapt_windows(self)
        self.title(f"本地文档定位工具 V{VERSION}")
        self.geometry("800x800")
        # 创建标签页
        self.main_notebook = ttk.Notebook(self)
        self.main_notebook.pack(expand=True, fill="both")
        self.frames = {}
        self.add_frame(DocsSearchFrame, "search", "文档搜索")
        self.add_frame(GitRepoBrowser, "search", "Git仓库浏览")

    def add_frame(
        self, frame_cls: Type[TabType], name: str, text: str, position=tk.END
    ) -> TabType:
        frame = frame_cls(self.main_notebook)
        # 
        self.frames[name] = frame
        self.main_notebook.add(frame, text=text)


if __name__ == "__main__":
    app = MainWindow()
    app.tk.call(
        "wm",
        "iconphoto",
        app._w,
        tk.PhotoImage(file=abs_static_resource_path("static/icon.png")),
    )
    # 更改窗口图标
    icon = TrayIcon(app)
    app.protocol("WM_DELETE_WINDOW", icon.on_exit)

    app.mainloop()
